/*
 * Copyright (c) 2008-2009 GWT Mosaic Georgios J. Georgopoulos.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.gwt.mosaic.pagebus.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.Command;

/**
 * 
 * 
 * @author georgopoulos.georgios(at)gmail.com
 * 
 */
public class PageBus {

  /**
   * @return a string constant (X.Y.Z) that indicates the version of the PageBus
   *         API.
   */
  public static native String getVersion()
  /*-{}-*/;

  /**
   * The subscribe operation subscribes to a subject and passes in the reference
   * to a callback function. The callback function is invoked with the
   * subscriber data and message whenever someone publishes a message on the
   * subscribed subject. Subscribed subjects can be wildcard subjects.
   * 
   * @param subject subject name (period-delimited string, for example:
   *          eg.customer.onSelect and log.info) to which to create the
   *          subscription
   * @param scope if the value is non-{@code null}, the object specified here
   *          becomes the context of the callback function, if the value is
   *          {@code null}, then the object window is used as the default
   *          context of the callback function
   * @param callback function for PageBus to invoke when a message is published
   *          on the subscribed subject (the parameter must NOT be {@code null}
   *          )
   * @parem subscriberData user-defined data ({@code null} values are permitted)
   * @parem filter optional filter callback function
   * @return a {@link Subscription} object
   * @throws PageBusBadName the specified subject name did not follow the
   *           subject rules
   * @throws PageBusBadParameter a {@code null} value was specified for the
   *           parameter callback
   */
  public static native Object subscribe(final String subject,
      final Object scope, final SubscriptionCallback callback,
      final JavaScriptObject subscriberData, final PageBusFilter filter)
  /*-{
    if (filter) {
      return $wnd.PageBus.subscribe(
        subject, scope, 
      
        function(subject, message, subscriberData) {
          callback.@org.gwt.mosaic.pagebus.client.SubscriptionCallback::execute(Ljava/lang/String;Ljava/lang/Object;)(subject, message);
        },
      
        subscriberData,
        
        function(subject, message, subscriberData) {
          return filter.@org.gwt.mosaic.pagebus.client.PageBusFilter::execute(Ljava/lang/String;Ljava/lang/Object;)(subject, message);
        }
      )    
    } else {
      return $wnd.PageBus.subscribe(
  	    subject, scope, 
  	  
  	    function(subject, message, subscriberData) {
  	      callback.@org.gwt.mosaic.pagebus.client.SubscriptionCallback::execute(Ljava/lang/String;Ljava/lang/Object;)(subject, message);
  	    },
  	  
  	    subscriberData
      );
    }
  }-*/;

  public static Object subscribe(final String subject, final Object scope,
      final SubscriptionCallback callback, final JavaScriptObject subscriberData) {
    return subscribe(subject, scope, callback, subscriberData, null);
  }

  public static Object subscribe(final String subject,
      final SubscriptionCallback callback) {
    return subscribe(subject, null, callback, null, null);
  }

  public static Object subscribe(final String subject, final Object scope,
      final SubscriptionCallback callback) {
    return subscribe(subject, scope, callback, null, null);
  }

  /**
   * The publish operation publishes one message on a subject.
   * 
   * @param subject subject name on which to publish the message (this must NOT
   *          be a wildcard subject).
   * @param message message content
   * 
   * @throws PageBusBadName the specified subject name did not follow the
   *           subject rules
   * @throws PageBusStackOverflow propable infinite publisher-subscriber loop
   *           detected and interrupted
   */
  public static native void publish(final String subject, final Object message)
  /*-{
  	$wnd.PageBus.publish(subject, message);
  }-*/;

  /**
   * The unsubscribe operation cancels a subscription, using the subscription
   * object returned by {@link #subscribe()} as a handle to the subscription.
   * 
   * @param subscription the {@link Subscription} object returned
   * @throws PageBusBadParameter the value of the subscription parameter is not
   *           a valid subscription
   */
  public static native void unsubscribe(final Subscription subscription)
  /*-{
    $wnd.PageBus.unsubscribe(subscription);
  }-*/;

  /**
   * The store operation stores a value in the PageBus repository under the
   * specified name. It then publishes a message on the specified name to notify
   * any subscribers of the change. If the value is {@code null}, then the store
   * operation removes the specified repository entry.
   * 
   * @param subject the name under which value is stored in repository, and on
   *          which repository then publishes notification message (must NOT be
   *          a wildcard subject or {@code null}.
   * @param value the value that is to be stored (typically object or string)
   * @param props the optional properties object, may contain an optional
   *          {@code quiet} property, which, if present and {@code true}, does
   *          not publish a notification message
   * 
   * @throws PageBusBadName the specified subject name did not follow the
   *           subject rules
   * @throws PageBusStackOverflow propable infinite publisher-subscriber loop
   *           detected and interrupted
   */
  public static native void store(final String subject, final Object value,
      JavaScriptObject props)
  /*-{}-*/;

  /**
   * The query operation finds all PageBus repository entries that match the
   * specified name and invokes a specified callback function to deliver these
   * values to the application.
   * 
   * @param subject
   * @param scope
   */
  public static native void query(final String subject,
      final JavaScriptObject scope, SubscriptionCallback callback, Object data,
      final Command filter)
  /*-{}-*/;

}
